﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using ComicIsland.Common;
using ComicIsland.Common.Entities;
using ComicIsland.Common.Entities.ComicDatabase;
using ComicIsland.Common.Entities.InterfaceJson;
using ComicIsland.Common.StorageHelper;
using ComicIsland.Common.WebHelper;
using Microsoft.Phone.BackgroundTransfer;

/**
 * 创建时间：2015/1/11 15:35:39
 * 作者：yong.blackcore
 * Email：itblackhole@outlook.com
 * QQ：50404503
 */
namespace ComicIsland.App.CIHelper
{
    public delegate void QueueSingletonStatusHandler(DbImage dbImage);
    public class BackgroundTransferQueueSingleton
    {
        public event QueueSingletonStatusHandler OnQueueSingletonStatus;        

        private static BackgroundTransferQueueSingleton instance = null;
        //程序运行时创建一个静态只读的辅助对象  
        private static readonly object syncRoot = new object();

        private BackgroundTransferQueueSingleton() { }

        public static BackgroundTransferQueueSingleton GetInstance()
        {
            //第一重判断，先判断实例是否存在，不存在再加锁处理  
            if (instance == null)
            {
                //加锁的程序在某一时刻只允许一个线程访问  
                lock (syncRoot)
                {
                    //第二重判断  
                    if (instance == null)
                    {
                        instance = new BackgroundTransferQueueSingleton();  //创建单例实例  
                    }
                }
            }
            return instance;
        }

        private int comicId = 0;

        /// <summary>
        /// 获取要下载的队列
        /// <para>1.获取图片队列</para>
        /// <para>2.无图片队列则获取章节队列</para>
        /// <para>3.无图片和章节队列则再获取漫画队列</para>
        /// </summary>
        /// <param name="comicId"></param>
        public void InitDownloadQueue(int comicId)
        {
            this.comicId = comicId;
            //图片队列
            var dbImageQueue = GetImageByPending(comicId);
            if (dbImageQueue != null)
            {
                InsertImageToBackgroundTransfer(dbImageQueue);
                return;
            }
            dbImageQueue = GetImageByDownloading(comicId);
            if (dbImageQueue != null)
            {
                InsertImageToBackgroundTransfer(dbImageQueue);
                return;
            }
            //无图片队列，则处理章节队列
            var dbChapterQueue = GetChapterByPending(comicId);
            if (dbChapterQueue != null)
            {
                GetChapterImage(dbChapterQueue);
                return;
            }

            //漫画队列
            //var dbComicQueue = 
        }



        private DbImage GetImageByPending(int comicId)
        {
            return App.comicDbHelper.ImageGetOneByDownloadStatus(DownloadComicChapterStatus.Pending, comicId);
        }

        private DbImage GetImageByDownloading(int comicId)
        {
            return App.comicDbHelper.ImageGetOneByDownloadStatus(DownloadComicChapterStatus.Downloading, comicId);
        }

        private DbChapter GetChapterByPending(int comicId)
        {
            return App.comicDbHelper.ChapterGetByDownloadStatus(DownloadComicChapterStatus.Pending, comicId);
        }


        /// <summary>
        /// 获取章节中的所有图片地址
        /// </summary>
        /// <param name="dbChapter"></param>
        private void GetChapterImage(DbChapter dbChapter)
        {
            string requestUrl = string.Concat(KEYS.REQUEST_HOST, string.Format("/comic/comicsread_v3?bookid={0}&partid={1}&partVersion=3", dbChapter.ComicId, dbChapter.PartId), "&", KEYS.REQUEST_QUERY_PLATFORM);
            LogHelper.LogInfo(requestUrl, this.GetType(), MethodBase.GetCurrentMethod());
            //
            string cacheDataKey = string.Concat(KEYS.CacheJsonPrefix, MD5.GetMd5String(requestUrl));
            LocalCacheDataHelper cacheHelper = new LocalCacheDataHelper();
            cacheHelper.GetDataFromLocalCache(cacheDataKey);
            if (!cacheHelper.IsReload)
            {
                //无需重新加载数据
                var rootCharacterString = JSONHelper.Deserialize<JsonComicContent>(cacheHelper.LocalCacheData);
                if (rootCharacterString != null && !string.IsNullOrWhiteSpace(rootCharacterString.Info))
                {
                    var saveDbImages = new ObservableCollection<DbImage>();
                    var itemsource = JSONHelper.Deserialize<ObservableCollection<JsonComicContentInfo>>(rootCharacterString.Info);
                    if (itemsource != null && itemsource.Count > 0)
                    {
                        foreach (JsonComicContentInfo jcci in itemsource)
                        {
                            saveDbImages.Add(new DbImage()
                            {
                                ComicId = dbChapter.ComicId,
                                PartId = dbChapter.PartId,
                                ImageUrl = jcci.Imgurl,
                                Referer = jcci.Referer,
                                ComicIdAndPartId = string.Concat(dbChapter.ComicId, "#", dbChapter.PartId),
                                DownloadStatus = DownloadComicChapterStatus.Pending.ToString()
                            });
                        }
                        //漫画的章节中的图片地址列表
                        if (saveDbImages != null && saveDbImages.Count > 0)
                        {
                            App.comicDbHelper.ImageInsertOrUpdate(saveDbImages);
                            InitDownloadQueue(this.comicId);
                        }
                    }
                }
                return;
            }
            //
            WebTaskHelper webTask = new WebTaskHelper(new Uri(requestUrl));
            IAsyncResult ia = webTask.BeginWebTask(delegate(IAsyncResult callBackResult)
            {
                try
                {
                    Deployment.Current.Dispatcher.BeginInvoke(() =>
                    {
                        #region **********获取结果处理**********
                        string result = webTask.EndWebTask(callBackResult);

                        if (string.IsNullOrWhiteSpace(result))
                        {
                            LogHelper.LogError("Result is empty.");
                            //MessageToastManager.Show("未获取到数据！", MessageToastLevel.Error);
                            return;
                        }
                        //
                        if (result.StartsWith("exception:"))
                        {
                            LogHelper.LogError(result);
                            return;
                        }
                        LogHelper.LogInfo(result, this.GetType(), MethodBase.GetCurrentMethod());
                        //

                        var rootCharacterString = JSONHelper.Deserialize<JsonComicContent>(result);
                        if (rootCharacterString != null && !string.IsNullOrWhiteSpace(rootCharacterString.Info))
                        {
                            var saveDbImages = new ObservableCollection<DbImage>();
                            var itemsource = JSONHelper.Deserialize<ObservableCollection<JsonComicContentInfo>>(rootCharacterString.Info);
                            if (itemsource != null && itemsource.Count > 0)
                            {
                                foreach (JsonComicContentInfo jcci in itemsource)
                                {
                                    saveDbImages.Add(new DbImage()
                                    {
                                        ComicId = dbChapter.ComicId,
                                        PartId = dbChapter.PartId,
                                        ImageUrl = jcci.Imgurl,
                                        Referer = jcci.Referer,
                                        ComicIdAndPartId = string.Concat(dbChapter.ComicId, "#", dbChapter.PartId),
                                        DownloadStatus = DownloadComicChapterStatus.Pending.ToString()
                                    });
                                }
                            }
                            //漫画的章节中的图片地址列表
                            if (saveDbImages != null && saveDbImages.Count > 0)
                            {
                                App.comicDbHelper.ImageInsertOrUpdate(saveDbImages);
                                InitDownloadQueue(this.comicId);
                            }
                        }
                        #endregion **********获取结果处理**********
                    });
                }
                catch (Exception err)
                {

                }
            }, webTask);
        }







        #region 下载队列处理
        private void InsertImageToBackgroundTransfer(DbImage imageQueue)
        {
            if (!(DownloadComicChapterStatus.Pending.ToString().Equals(imageQueue.DownloadStatus) || DownloadComicChapterStatus.Downloading.ToString().Equals(imageQueue.DownloadStatus)))
            {
                this.InitDownloadQueue(this.comicId);
                return;
            }

            #region 图片文件是否已经存在
            string filePath = string.Concat(KEYS.ComicIslandCacheDirectory, "/", KEYS.CacheImagePrefix, imageQueue.ComicId, "_", imageQueue.PartId, "_", MD5.GetMd5String(imageQueue.ImageUrl));
            LogHelper.LogInfo(filePath, this.GetType(), MethodBase.GetCurrentMethod());
            if (IsolatedStorageHelper.Instance.FileExists(filePath))
            {
                //更新缓存状态                        
                App.comicDbHelper.ImageUpdateStatus(imageQueue, DownloadComicChapterStatus.Completed);
                LogHelper.LogInfo("已经下载了，重新获取队列！", this.GetType(), MethodBase.GetCurrentMethod());
                this.InitDownloadQueue(this.comicId);
                return;
            }
            #endregion 图片文件是否已经存在


            Uri transferUri = new Uri(Uri.EscapeUriString(imageQueue.ImageUrl), UriKind.RelativeOrAbsolute);
            BackgroundTransferRequest transferRequest = new BackgroundTransferRequest(transferUri);
            transferRequest.Method = "GET";
            Uri downloadUri = new Uri(string.Concat("shared/transfers/", KEYS.CacheImagePrefix, imageQueue.ComicId, "_", imageQueue.PartId, "_", MD5.GetMd5String(imageQueue.ImageUrl)), UriKind.RelativeOrAbsolute);
            transferRequest.DownloadLocation = downloadUri;
            LogHelper.LogInfo(downloadUri.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
            //
            transferRequest.Tag = JSONHelper.Serialize<DbImage>(imageQueue);
            transferRequest.TransferPreferences = TransferPreferences.AllowCellularAndBattery;
            try
            {
                if (0 < BackgroundTransferService.Requests.Where(p => p.DownloadLocation == transferRequest.DownloadLocation).Count())
                {
                    //队列已经存在
                    RemoveTransferRequest(transferRequest.RequestId);
                }
                transferRequest.TransferProgressChanged += new EventHandler<BackgroundTransferEventArgs>(this.transferRequest_TransferProgressChanged);
                transferRequest.TransferStatusChanged += new EventHandler<BackgroundTransferEventArgs>(this.transferRequest_TransferStatusChanged);
                this.UpdateBackgroundTransfer(transferRequest);
                BackgroundTransferService.Add(transferRequest);
                imageQueue.DownloadStatus = DownloadComicChapterStatus.Downloading.ToString();
                //更新表数据
                App.comicDbHelper.ImageUpdateStatus(imageQueue, DownloadComicChapterStatus.Downloading);
            }
            catch (Exception err) { LogHelper.LogError(err.ToString(), this.GetType(), MethodBase.GetCurrentMethod()); }
        }

        /// <summary>
        /// TransferStatus状态属性变更时触发
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void transferRequest_TransferStatusChanged(object sender, BackgroundTransferEventArgs e)
        {
            UpdateBackgroundTransfer(e.Request);
        }

        void transferRequest_TransferProgressChanged(object sender, BackgroundTransferEventArgs e)
        {
            //下载进度变更
            //LogHelper.LogInfo(string.Concat(e.Request.TotalBytesToReceive, "/", e.Request.BytesReceived), this.GetType(), MethodBase.GetCurrentMethod());
        }

        void UpdateBackgroundTransfer(BackgroundTransferRequest transfer)
        {
            try
            {


                switch (transfer.TransferStatus)
                {
                    case TransferStatus.Completed:
                        if (transfer.StatusCode == 200 || transfer.StatusCode == 206)
                        {
                            //从队列移除
                            RemoveTransferRequest(transfer.RequestId);
                            //
                            DbImage dbImage = JSONHelper.Deserialize<DbImage>(transfer.Tag);
                            string filefullpath = string.Empty;
                            if (dbImage == null)
                            {
                                return;
                            }
                            string filename = string.Concat(KEYS.ComicIslandCacheDirectory, "/", KEYS.CacheImagePrefix, dbImage.ComicId, "_", dbImage.PartId, "_", MD5.GetMd5String(dbImage.ImageUrl));
                            LogHelper.LogInfo(filename, this.GetType(), MethodBase.GetCurrentMethod());

                            //将下载的文件移到指定目录下
                            using (IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication())
                            {
                                try
                                {
                                    if (!isoStore.FileExists(filename))
                                    {
                                        //isoStore.DeleteFile(filename);
                                        isoStore.MoveFile(transfer.DownloadLocation.OriginalString, filename);
                                    }
                                }
                                catch (Exception err)
                                {
                                    LogHelper.LogError(err.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
                                }
                            }
                            //更新缓存状态                        
                            App.comicDbHelper.ImageUpdateStatus(dbImage, DownloadComicChapterStatus.Completed);
                            //激活事件（主要用于更新UI）
                            if(OnQueueSingletonStatus != null)
                            {
                                OnQueueSingletonStatus(dbImage);
                            }
                            //
                            if (BackgroundTransferService.Requests.Count() <= 0)
                            {
                                LogHelper.LogInfo("队列处理完成了，取新队列！", this.GetType(), MethodBase.GetCurrentMethod());
                                this.InitDownloadQueue(this.comicId);
                            }
                            else
                            {
                                foreach (BackgroundTransferRequest btr in BackgroundTransferService.Requests)
                                {
                                    UpdateBackgroundTransfer(btr);
                                }
                            }

                        }
                        else
                        {
                            //下载不正确时，从队列移除或做其它处理
                            RemoveTransferRequest(transfer.RequestId);
                        }
                        break;
                }
            }
            catch (Exception err)
            {
                LogHelper.LogError(err.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
            }
        }

        private void RemoveTransferRequest(string transferID)
        {
            // Use Find to retrieve the transfer request with the specified ID.
            BackgroundTransferRequest transferToRemove = BackgroundTransferService.Find(transferID);

            // Try to remove the transfer from the background transfer service.
            try
            {
                BackgroundTransferService.Remove(transferToRemove);
            }
            catch (Exception e)
            {
                // Handle the exception.
            }
        }
        #endregion 下载队列处理
    }
}
